#include "ArmyState.h"
#include "UserAPI.h"
#include "BasicAI.h"
#include "params.h"

using namespace ArmyStateNS;

bool WithdrawState::find_safe_move()
{
	LOG << "try to find a safe move" << endl;
	BasicAI *ai = BasicAI::instance();
	UserAPI &api = ai->get_api();
	Army *army = api.GetCntArmy();

	int width = api.game->map->sizeX, height = api.game->map->sizeY;
	Position best(-1, -1);
	int min = INFINITY;
	for (int i = 0; i < width; i ++)
		for (int j = 0; j < height; j ++) {
			Position t(i, j);
			if (!api.CheckPosition(t)) continue;
			Army *enemy = api.GetNearestArmy(t, api.op_army);
			if (enemy && api.HamDistance(t, enemy->pos) <= 9) continue;

			if (api.HamDistance(t, army->pos) < min)
			{
				min = api.HamDistance(t, army->pos);
				best = t;
			}
		}

	LOG << "try to find a safe move failed" << endl;
	if (min > 5) return false;
	api.Move(ai->get_action_queue(), army->pos, best);
	LOG << "try to find a safe move succeeded" << endl;
	return true;
}

bool WithdrawState::find_strong_fellow()
{
	LOG << "try to find a strong fellow" << endl;
	BasicAI *ai = BasicAI::instance();
	UserAPI &api = ai->get_api();
	Army *army = api.GetCntArmy();

	Army *best = NULL;
	for (int i = 0; i < (int) api.my_army.size(); ++i)
		if (api.my_army[i] != army && (best == NULL || api.my_army[i]->numSoldier > best->numSoldier))
			best = api.my_army[i];

	if (!best) return false;
	api.MoveToRegion(ai->get_action_queue(), army->pos, best->pos, 1);
	LOG << "try to find a strong fellow succeeded" << endl;
	return true;
}

void WithdrawState::execute()
{
	/*
		If there's extremely strong enemy around, 
			try to find a safe move at first,
			if I cannot find such a move, direclty move my strongest fellow.
			if I am along, sadly, simply find someone to attack. Good luck!
		otherwise, 
			if a city need management, go ahead
			otherwise, if we can find a city to recruit (or switch army), go ahead
			otherwise, if we can find a city to fight, go ahead
			otherwise, find a safe move at first,
	 */

	//	TODO	try to switch army

	BasicAI *ai = BasicAI::instance();
	UserAPI &api = ai->get_api();
	Army *army = api.GetCntArmy();
	
	vector<Army*> op_troop = api.GetOpArmyAround(army->pos);
	int op_army_count = api.GetArmyCount(op_troop);
	if (op_army_count > army->numSoldier * 2)
	{
		LOG << "too strong enemies, find a quick way out" << endl;
		if (find_safe_move()) return;
		if (find_strong_fellow()) return;
		enter_state(m_name, this, new OffensiveBattleState(m_name));
		return;
	}

	LandCity *city = api.GetCity(army->pos);
	if (city && city->owner == api.get_my_id() && city->hasBarrack)
		api.Recruit(ai->get_action_queue(), city->totalSoldier);

	LOG << "try to find a city to manage" << endl;
	Position p;
	if (ManageState::get_manager_offer(p))
	{
		enter_state(m_name, this, new ManageState(m_name, p));
		return;
	}

	LOG << "try to find a city to recruit" << endl;
	int recruit_city_dist = INFINITY;
	for (int i = 0; i < (int)api.all_cities.size(); ++i)
	{
		LandCity *c = api.all_cities[i];
		if (c && c->owner == api.get_my_id() && c->hasBarrack && api.HamDistance(api.GetCityCenter(c), army->pos) < recruit_city_dist)
		{
			LOG << "city " << toString(api.GetCityCenter(c)) << " totalSoldier = " << c->totalSoldier << endl;
			if (c->totalSoldier >= army->numSoldier / 2 || c->totalSoldier >= 1000)
			{
				recruit_city_dist = api.HamDistance(api.GetCityCenter(c), army->pos);
				p = api.GetCityCenter(c);
			}
		}
	}
	if (recruit_city_dist < INFINITY)
	{
		api.MoveToRegion(ai->get_action_queue(), army->pos, p, 1);
		return;
	}

	LOG << "try to find a weak city to attack" << endl;

	LandCity *best_city = NULL;
	int weakest_power = INFINITY;
	for (int i = 0; i < (int) api.all_cities.size(); ++i)
	{
		LandCity *city = api.all_cities[i];
		Position center = api.GetCityCenter(city);

		vector<Army*> op_troop = api.GetOpArmyAround(center);
		int op_count = api.GetArmyCount(op_troop);
		
		int power = city->HP * 10 + op_count;
		vector<ActionBase*> ret;
		if (power < weakest_power && api.FindSafeWayToRegion(ret, army->pos, center, army->numSoldier))
		{
			weakest_power = power;
			best_city = city;
		}
	}

	if (weakest_power < army->numSoldier)
	{
		api.FindSafeWayToRegion(ai->get_action_queue(), army->pos, api.GetCityCenter(best_city), army->numSoldier);
		return;
	} else
	{
		find_safe_move();
		return;
	}
}